#include "scheduler.h"

#include <string.h>

/**
 * @brief 初始化调度器
 *
 * @param scheduler 调度器句柄
 */
void SchedulerInit(SchedulerHandler *scheduler)
{
    memset(scheduler, 0, sizeof(SchedulerHandler));
}

/**
 * @brief 调度器主循环函数
 *
 * @param scheduler 调度器句柄
 */
void SchedulerTick(SchedulerHandler *scheduler)
{
    uint8_t task_num = scheduler->task_num;
    uint8_t index = 0;
    SchedulerTaskHandler *task = scheduler->tasks;

    while (task_num && index < SCHEDULER_TASK_MAX_NUM)
    {
        if (task->status == SCHEDULER_TASK_RUNNING)
        {
            SchedulerTaskTick current_tick = SchedulerGetTick();
            if (task->tick <= current_tick)
            {
                SCHEDULER_RUN_TASK(task);

                if (task->interval)
                {
                    task->tick += task->interval;
                }
                else
                {
                    task->status = SCHEDULER_TASK_NONE;
                }
            }
            task_num--;
        }
        else if (task->status == SCHEDULER_TASK_STOPPED)
        {
            task_num--;
        }

        index++;
        task++;
    }
}

/**
 * @brief 获取当前时间戳
 *
 * @return SchedulerTaskTick 当前时间戳
 */
__attribute__((weak)) SchedulerTaskTick SchedulerGetTick(void)
{
    // Override me
    return 0;
}

/**
 * @brief 添加任务到调度器
 *
 * @param scheduler 调度器句柄
 * @param func 任务函数
 * @param arg 任务函数参数
 * @param delay 延迟时间
 * @param interval 间隔时间
 * @return SchedulerTaskHandler* 任务句柄
 */
SchedulerTaskHandler *SchedulerAddTask(SchedulerHandler *scheduler, SchedulerTaskFunc func, void *arg, SchedulerTaskTick delay, SchedulerTaskTick interval)
{
    uint8_t index;

    // Seek for free slot
    if (scheduler->task_num > SCHEDULER_TASK_MAX_NUM)
    {
        return NULL;
    }

    for (index = 0; index < SCHEDULER_TASK_MAX_NUM; index++)
    {
        if (scheduler->tasks[index].status == SCHEDULER_TASK_NONE)
        {
            SchedulerTaskTick current_tick = SchedulerGetTick();
            SchedulerTaskHandler *task = scheduler->tasks + index;

            task->status = SCHEDULER_TASK_RUNNING;
            task->interval = interval;
            task->func = func;
            task->arg = arg;
            if (delay)
            {
                task->tick = delay + current_tick;
            }
            else if (interval)
            {
                task->tick = interval + current_tick;
            }
            else
            {
                task->tick = 0;
            }
            task->task_num_p = &scheduler->task_num;

            scheduler->task_num++;

            break;
        }
    }

    return scheduler->tasks + index;
}

/**
 * @brief 移除任务
 *
 * @param task 任务句柄
 */
void SchedulerRemoveTask(SchedulerTaskHandler *task)
{
    task->status = SCHEDULER_TASK_NONE;
    (*task->task_num_p)--;
}

/**
 * @brief 恢复任务
 *
 * @param task 任务句柄
 */
void SchedulerResumeTask(SchedulerTaskHandler *task)
{
    task->status = SCHEDULER_TASK_RUNNING;
    task->tick = task->interval;
}

/**
 * @brief 停止任务
 *
 * @param task 任务句柄
 */
void SchedulerStopTask(SchedulerTaskHandler *task)
{
    task->status = SCHEDULER_TASK_STOPPED;
}